﻿using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;

namespace SyncTcpClient
{
    public partial class frmSyncTcpClient : Form
    {
        //读写流、TcpClient对象
        private TcpClient tcpClient;
        private NetworkStream networkStream;
        private BinaryReader br;
        private BinaryWriter bw;
        private int sendCount = 1;
        private int receiveCount = 10;
        /**********************************************************/
        //此处与服务端端完全一致
        //显示消息
        private delegate void ShwMsgforViewCallBack(string str);
        ShwMsgforViewCallBack shwMsgforViewCallBack;
        //显示状态
        private delegate void ShwStatusInfoCallBack(string str);
        ShwStatusInfoCallBack shwStatusInfoCallBack;
        //显示进度
        private delegate void ShwProgressProcCallBack(int process);
        ShwProgressProcCallBack shwProgressProcCallBack;
        //重置文本消息
        private delegate void ResetMsgTxtCallBack();
        ResetMsgTxtCallBack resetMsgTxtCallBack;
        //异常委托
        /**********************************************************/
        public frmSyncTcpClient()
        {
            /**********************************************************/
            InitializeComponent();
            //此处与服务端端完全一致
            //显示消息
            shwMsgforViewCallBack = new ShwMsgforViewCallBack(ShwMsgForView);
            //显示状态
            shwStatusInfoCallBack = new ShwStatusInfoCallBack(ShwStatusInfo);
            //显示进度
            shwProgressProcCallBack = new ShwProgressProcCallBack(ShwProgressProc);
            //重置文本消息
            resetMsgTxtCallBack = new ResetMsgTxtCallBack(ResetMsgTxt);
            /**********************************************************/
            IPAddress[] ipAddress = Dns.GetHostAddresses("");
            tbxSrvIp.Text = ipAddress[0].ToString();
            tbxSrvIp.SelectAll();
            tbxPort.Text = "51888";
            tbxSendCount.Text = sendCount.ToString();
            tbxReceiveCount.Text = receiveCount.ToString();
            toolStripProcessProc.Minimum = 0;

        }

        private void ResetMsgTxt()
        {
            tbxMsg.Text = "";
            tbxMsg.Focus();
        }

        private void ShwProgressProc(int process)
        {
            toolStripProcessProc.Value = process;
        }

        private void ShwStatusInfo(string str)
        {
            toolStripStatusInfo.Text = str;
        }

        private void ShwMsgForView(string str)
        {
            lstbxMsgView.Items.Add(str);
            lstbxMsgView.TopIndex = lstbxMsgView.Items.Count - 1;
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            toolStripProcessProc.Maximum = 100;
            toolStripProcessProc.Value = 0;
            Thread threadConnect = new Thread(new ThreadStart(ConnectToServer));
            threadConnect.Start();
        }

        private void ConnectToServer()
        {
            try
            {
                statusStripInfo.Invoke(shwStatusInfoCallBack, "Connectting..");
                IPHostEntry remoteHost = Dns.GetHostEntry(tbxSrvIp.Text);
                tcpClient = new TcpClient();
                statusStripInfo.Invoke(shwProgressProcCallBack, 1);
                tcpClient.Connect(remoteHost.HostName, int.Parse(tbxPort.Text));
                statusStripInfo.Invoke(shwProgressProcCallBack, 100);
                DateTime now = DateTime.Now;
                while (now.AddSeconds(1) > DateTime.Now) { }
                if(tcpClient!=null)
                {
                    statusStripInfo.Invoke(shwStatusInfoCallBack, "Connection!");
                    networkStream = tcpClient.GetStream();
                    br = new BinaryReader(networkStream);
                    bw = new BinaryWriter(networkStream);
                }
            }
            catch (Exception e)
            {
                statusStripInfo.Invoke(shwStatusInfoCallBack, "Connected Failed!");
                DateTime now = DateTime.Now;
                while (now.AddSeconds(1) > DateTime.Now) { }
                statusStripInfo.Invoke(shwStatusInfoCallBack, "Ready");
                statusStripInfo.Invoke(shwProgressProcCallBack, 0);
                lstbxMsgView.Invoke(shwMsgforViewCallBack, e.Message);
            }
        }

        private void btnReceive_Click(object sender, EventArgs e)
        {
            receiveCount = int.Parse(tbxReceiveCount.Text);
            toolStripProcessProc.Maximum = receiveCount;
            toolStripProcessProc.Value = 0;
            Thread threadReceive = new Thread(new ThreadStart(ReceiveMessage));
            threadReceive.Start();
        }
        /// <summary>
        /// Receive message
        /// </summary>
        private void ReceiveMessage()
        {
            statusStripInfo.Invoke(shwStatusInfoCallBack, "Receiving...");
            for(int i=0;i<receiveCount;i++)
            {
                try
                {
                    string rcvMsgStr = br.ReadString();
                    statusStripInfo.Invoke(shwProgressProcCallBack, i + 1);
                    if(rcvMsgStr!=null)
                    {
                        lstbxMsgView.Invoke(shwMsgforViewCallBack, rcvMsgStr);
                    }
                }
                catch (Exception)
                {
                    if(br!=null)
                    {
                        br.Close();
                    }
                    if (bw!=null)
                    {
                        bw.Close();
                    }
                    if (tcpClient!=null)
                    {
                        tcpClient.Close();
                    }
                    statusStripInfo.Invoke(shwStatusInfoCallBack, "Disconnect!");
                    statusStripInfo.Invoke(shwProgressProcCallBack, 0);
                    break;
                }
            }
            statusStripInfo.Invoke(shwStatusInfoCallBack, "Receives "+receiveCount+" messages");
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            sendCount = int.Parse(tbxSendCount.Text);
            toolStripProcessProc.Maximum = sendCount;
            toolStripProcessProc.Value = 0;
            Thread threadSend = new Thread(new ParameterizedThreadStart(SendMessage));
            threadSend.Start(tbxMsg.Text);
        }

        /// <summary>
        /// Send message
        /// </summary>
        private void SendMessage(object state)
        {
            statusStripInfo.Invoke(shwStatusInfoCallBack, "Sending...");
            for (int i = 0; i < sendCount; i++)
            {
                try
                {
                    bw.Write(state.ToString());
                    statusStripInfo.Invoke(shwProgressProcCallBack, i + 1);
                    Thread.Sleep(1000);
                    bw.Flush();
                }
                catch (Exception)
                {
                    if(br!=null)
                    {
                        br.Close();
                    }
                    if(bw!=null)
                    {
                        br.Close();
                    }
                    if (tcpClient!=null)
                    {
                        tcpClient.Close();
                    }
                    statusStripInfo.Invoke(shwStatusInfoCallBack, "Disconnect!");
                    statusStripInfo.Invoke(shwProgressProcCallBack, 0);
                    break;
                }
            }
            statusStripInfo.Invoke(shwStatusInfoCallBack, "Over!");
            Thread.Sleep(1000);
            statusStripInfo.Invoke(shwProgressProcCallBack, 0);
            tbxMsg.Invoke(shwMsgforViewCallBack, null);
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            if (br!=null)
            {
                br.Close();
            }
            if (bw!=null)
            {
                bw.Close();
            }
            if (tcpClient!=null)
            {
                tcpClient.Close();
            }
            toolStripStatusInfo.Text = "DisConnect!";
            toolStripProcessProc.Value = 0;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            lstbxMsgView.Items.Clear();
        }
    }
}
